package OrderQueue

import (
	"crypto/md5"
	"errors"
	"fmt"
	"gdshop-back-end-go/common/libs/genids"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/os/glog"
	"github.com/gogf/gf/util/gconv"
	jsoniter "github.com/json-iterator/go"
)

func getQueueCli() Client {
	return Client{
		Conn: g.Redis("queue").Conn().Conn,
	}
}

// 统一管理，后面方便替换源

// 处理订单队列
func InitOrderQueue() {
	// 关闭订单定时器，按秒执行
	//initSubmitOrderQueue()
	go initSubmitOrderQueue2()
}

// 获取下一次执行时间，通过这里控制下次是否执行
func gotoNextExecTime(topic string, data OrderQueue) {
	nextExeTimes := g.Cfg().GetInts("queue." + topic + ".DelayOnFailure")
	if len(nextExeTimes) < 1 {
		return
	}
	// 有设置的话
	if len(nextExeTimes) > data.ReTry {
		delayTime := nextExeTimes[data.ReTry]
		// 重试测试加一
		data.ReTry++
		// 重新加入队列
		_, err := PushQueue(topic, data, delayTime)
		if err != nil {
			glog.Async().Cat("OrderQueue").Error("handleOrderQueue PushQueue error ", err.Error())
			return
		}
	}
}
func getMessageId() string {
	id, err := genids.ToolsGetNextId()
	if err != nil {
		return ""
	}
	return fmt.Sprintf("%x", md5.Sum(gconv.Bytes(id)))
}

// PushQueue 统一的加入方法
func PushQueue(topic string, data OrderQueue, delayTime int) (string, error) {
	// 加入队列
	messageId := getMessageId()
	if messageId == "" {
		return "", errors.New("生成消息ID失败")
	}
	body, err := jsoniter.MarshalToString(data)
	if err != nil {
		return "", err
	}
	msg := Message{
		ID:    messageId,
		Topic: topic,
		Body:  body,
	}
	cli := getQueueCli()
	_, err = cli.Push(msg, delayTime, 86400)
	if err != nil {
		return "", err
	}

	return messageId, nil
}

// PushQueueInterface 统一的加入方法
func PushQueueInterface(topic string, data interface{}, delayTime int) (string, error) {
	// delayTime 最少给 1 秒，防止无事务时数据不完整
	if delayTime < 1 {
		delayTime = 1
	}
	// 加入队列
	messageId := getMessageId()
	if messageId == "" {
		return "", errors.New("生成消息ID失败")
	}
	body, err := jsoniter.MarshalToString(data)
	if err != nil {
		return "", err
	}
	message := Message{
		ID:    messageId,
		Topic: topic,
		Body:  body,
	}
	cli := getQueueCli()
	_, err = cli.Push(message, delayTime, 60)
	if err != nil {
		return "", err
	}
	defer cli.Conn.Close()
	// 返回
	return messageId, nil
}

// 处理队列
func handleOrderQueue(job *Message) {
	var tmp OrderQueue
	err := gconv.Struct(job.Body, &tmp)
	if err != nil {
		glog.Async().Cat("OrderQueue").Error("handleOrderQueue gconv.Struct error ", err.Error())
		return
	}
	isSuccess := false
	switch tmp.Type {
	case 0:
		/*jieguo := OrderService.CloseNoPayOrder(nil, tmp.OrderId)
		if jieguo.Code != 0 {
			isSuccess = false
			glog.Async().Cat("OrderQueue").Error("handleOrderQueue exe error Message:",
				jieguo.Message, " data:", tmp)
		} else {
			isSuccess = true
		}*/
	}
	// 执行失败，判断是否有下一次执行
	if isSuccess == false {
		gotoNextExecTime(job.Topic, tmp)
	}
}
